//------------------------------------------------------------------------------
//
//  TeleOperation Types
//
//  Written Jan 2008 by Trevor Taylor, Software Technology, Australia
//
//------------------------------------------------------------------------------

using Microsoft.Ccr.Core;
using Microsoft.Dss.Core.Attributes;
using Microsoft.Dss.ServiceModel.Dssp;
using System;
using System.Collections.Generic;
using W3C.Soap;
using teleoperation = ProMRDS.Robotics.TeleOperation;

// For declaring generic Form events
using System.Windows.Forms;
// For HttpGet
using Microsoft.Dss.Core.DsspHttp;


namespace ProMRDS.Robotics.TeleOperation
{

    #region Contract

    /// <summary>
    /// TeleOperation Contract class
    /// </summary>
    public sealed class Contract
    {
        
        /// <summary>
        /// The Dss Service contract
        /// </summary>
        public const String Identifier = "http://www.promrds.com/contracts/2008/01/teleoperation.html";
    }

    #endregion

    #region State

    /// <summary>
    /// The TeleOperation State
    /// </summary>
    [DataContract()]
    public class TeleOperationState
    {
        /// <summary>
        /// Host computer
        /// </summary>
        [DataMember]
        public string Host;

        /// <summary>
        /// Port to use 
        /// </summary>
        [DataMember]
        public ushort Port;

        [DataMember]
        public bool Connected;

        [DataMember]
        public string DriveService;

        [DataMember]
        public string WebCamService;

        /// <summary>
        /// Option Settings 
        /// </summary>
        [DataMember]
        public GUIOptions Options;
    }

    // This is an "options bag" for the option settings.
    // An instance is added to the State above.
    [DataContract]
    public class GUIOptions
    {
        // Initial position of the main Window
        [DataMember]
        public int WindowStartX;
        [DataMember]
        public int WindowStartY;

        // Initial position of the WebCam Window
        [DataMember]
        public int WebCamStartX;
        [DataMember]
        public int WebCamStartY;

        // Dead Zone parameters
        // The "deadzone" is a region where the movement of the
        // joystick has no effect. The implementation here snaps
        // the x or y coordinate to zero when it is within the
        // DeadZoneX or Y range. This allows the robot to drive
        // dead ahead, or to rotate perfectly. The old code did
        // not have an exact center and so the wheel power could
        // never be balanced!
        // For my Lego NXT, I use values of 80 for each of these.
        // This amounts to only a few pixels on the screen (because
        // the "yoke" range is +/- 1000). If you set it too high,
        // you won't get any movement! However, you can set it to
        // zero if you don't want this feature.
        [DataMember]
        public double DeadZoneX;
        [DataMember]
        public double DeadZoneY;
        // Scale Factors
        // Because different robots have different drive
        // characteristics, and their users have different reaction
        // times and/or preferences, there are now two parameters
        // that affect the scaling of the drive power. The Translate
        // Scale Factor adjusts the forward/backward take-up rate,
        // i.e. moving the joystick forwards or backwards (which is
        // up or down on the "yoke" on the screen).
        // The Rotate Scale Factor adjusts the rate for the the
        // left/right (side to side) movements to control the speed
        // of rotation.
        // Usually you want different scale factors for these two
        // types of motions because it is hard to control turns if
        // the robot spins at the same speed that it uses to drives
        // forwards.
        // For my Lego NXT, I use values of 0.8 for Translate and
        // 0.2 for Rotate.
        //
        // NOTE: The results of the motor power calculations are
        // limited to +/- 1000, which translates to +/- 1.0 when
        // sent to the differentialdrive service. This means that
        // if you set Translate to 2.0 for instance, then it will
        // max out halfway between the center and the maximum
        // (top) of the joystick travel. This makes the speed much
        // more responsive to joystick movements. Conversely, you
        // can set a value of 0.5 and then the robot will only ever
        // reach half of its possible drive speed (approximately).
        [DataMember]
        public double TranslateScaleFactor;
        [DataMember]
        public double RotateScaleFactor;

        // "Speed" to use for the motors (actually power)
        // NOTE: This is in the range 0-1000 because it has to match
        // the game controller range. This is should be cleaned up!
        [DataMember]
        public double MotionSpeed;
        // Values for use with RotateDegrees and DriveDistance
        [DataMember]
        public double DriveDistance;
        [DataMember]
        public double RotateAngle;

//        [DataMember]
//        public int CameraInterval;
    }

    #endregion

    #region Main Operations Port

    /// <summary>
    /// TeleOperation Main Operations Port
    /// </summary>
    [ServicePort()]
    public class TeleOperationOperations :
        PortSet<DsspDefaultLookup, DsspDefaultDrop, Get, HttpGet, HttpPost>
    {
    }

    #endregion

    #region Operations

    /// <summary>
    /// TeleOperation Get Operation
    /// </summary>
    public class Get : Get<GetRequestType, PortSet<TeleOperationState, Fault>>
    {
        
        /// <summary>
        /// TeleOperation Get Operation
        /// </summary>
        public Get()
        {
        }
        
        /// <summary>
        /// TeleOperation Get Operation
        /// </summary>
        public Get(Microsoft.Dss.ServiceModel.Dssp.GetRequestType body) : 
                base(body)
        {
        }
        
        /// <summary>
        /// TeleOperation Get Operation
        /// </summary>
        public Get(Microsoft.Dss.ServiceModel.Dssp.GetRequestType body, Microsoft.Ccr.Core.PortSet<TeleOperationState,W3C.Soap.Fault> responsePort) : 
                base(body, responsePort)
        {
        }
    }

    #endregion

    #region General Form Operations
    // This is the base class for all Form event messages
    public class FormEvent
    {
        private Form _theForm;

        public Form Form
        {
            get { return _theForm; }
            set { _theForm = value; }
        }

        public FormEvent(Form form)
        {
            _theForm = form;
        }
    }

    public class OnLoad : FormEvent
    {
        public OnLoad(Form form)
            : base(form)
        {
        }
    }

    public class OnClosed : FormEvent
    {
        public OnClosed(Form form)
            : base(form)
        {
        }
    }

    #endregion

}
